﻿

using System;
using System.Collections.Generic;
using System.Linq;
using Payroll.BusinessLogic.Caching;
using Payroll.BusinessLogic.Configuration.Settings;
using Payroll.BusinessLogic.Data;
using Payroll.BusinessLogic.Infrastructure;
using Payroll.Common;
using Payroll.Common.Utils;

namespace Payroll.BusinessLogic.Security
{
    /// <summary>
    /// IP Blacklist service implementation
    /// </summary>
    public partial class BlacklistService : IBlacklistService
    {
        #region Constants
        private const string BLACKLIST_ALLIP_KEY = "Nop.blacklist.ip.all";
        private const string BLACKLIST_ALLNETWORK_KEY = "Nop.blacklist.network.all";
        private const string BLACKLIST_IP_PATTERN_KEY = "Nop.blacklist.ip.";
        private const string BLACKLIST_NETWORK_PATTERN_KEY = "Nop.blacklist.network.";
        #endregion

        #region Fields

        /// <summary>
        /// Object context
        /// </summary>
        private readonly PayrollHRDataContext m_context;

        /// <summary>
        /// Cache manager
        /// </summary>
        private readonly ICacheManager _cacheManager;

        #endregion

        #region Ctor

        /// <summary>
        /// Ctor
        /// </summary>
        /// <param name="context">Object context</param>
        public BlacklistService(PayrollHRDataContext context)
        {
            this.m_context = context;
            this._cacheManager = new PayrollRequestCache();
        }

        #endregion

        #region Utilities

        /// <summary>
        /// This encodes the string representation of an IP address to a uint, but
        /// backwards so that it can be used to compare addresses. This function is
        /// used internally for comparison and is not valid for valid encoding of
        /// IP address information.
        /// </summary>
        /// <param name="ipAddress">A string representation of the IP address to convert</param>
        /// <returns>Returns a backwards uint representation of the string.</returns>
        private uint IpAddressToLongBackwards(string ipAddress)
        {
            byte[] byteIp = System.Net.IPAddress.Parse(ipAddress).GetAddressBytes();

            uint ip = (uint)byteIp[0] << 24;
            ip += (uint)byteIp[1] << 16;
            ip += (uint)byteIp[2] << 8;
            ip += (uint)byteIp[3];

            return ip;
        }

        /// <summary>
        /// Compares two IP addresses for equality. 
        /// </summary>
        /// <param name="ipAddress1">The first IP to compare</param>
        /// <param name="ipAddress2">The second IP to compare</param>
        /// <returns>True if equal, false if not.</returns>
        private bool AreEqual(string ipAddress1, string ipAddress2)
        {
            // convert to long in case there is any zero padding in the strings
            return IpAddressToLongBackwards(ipAddress1) == IpAddressToLongBackwards(ipAddress2);
        }

        /// <summary>
        /// Compares two string representations of an Ip address to see if one
        /// is greater than the other
        /// </summary>
        /// <param name="toCompare">The IP address on the left hand side of the greater 
        /// than operator</param>
        /// <param name="compareAgainst">The Ip address on the right hand side of the 
        /// greater than operator</param>
        /// <returns>True if ToCompare is greater than CompareAgainst, else false</returns>       
        private bool IsGreater(string toCompare, string compareAgainst)
        {
            // convert to long in case there is any zero padding in the strings
            return IpAddressToLongBackwards(toCompare) > IpAddressToLongBackwards(compareAgainst);
        }

        /// <summary>
        /// Compares two string representations of an Ip address to see if one
        /// is less than the other
        /// </summary>
        /// <param name="toCompare">The IP address on the left hand side of the less 
        /// than operator</param>
        /// <param name="compareAgainst">The Ip address on the right hand side of the 
        /// less than operator</param>
        /// <returns>True if ToCompare is greater than CompareAgainst, else false</returns>
        private bool IsLess(string toCompare, string compareAgainst)
        {
            // convert to long in case there is any zero padding in the strings
            return IpAddressToLongBackwards(toCompare) < IpAddressToLongBackwards(compareAgainst);
        }

        /// <summary>
        /// Determines whether a specified object is equal to another object
        /// </summary>
        /// <param name="toCompare">The IP address on the left hand side of the less 
        /// than operator</param>
        /// <param name="compareAgainst">The Ip address on the right hand side of the 
        /// less than operator</param>
        /// <returns>Result</returns>
        private bool IsEqual(string toCompare, string compareAgainst)
        {
            return IpAddressToLongBackwards(toCompare) == IpAddressToLongBackwards(compareAgainst);
        }

        /// <summary>
        /// Compares two string representations of an Ip address to see if one
        /// is greater than or equal to the other.
        /// </summary>
        /// <param name="toCompare">The IP address on the left hand side of the greater 
        /// than or equal operator</param>
        /// <param name="compareAgainst">The Ip address on the right hand side of the 
        /// greater than or equal operator</param>
        /// <returns>True if ToCompare is greater than or equal to CompareAgainst, else false</returns>
        private bool IsGreaterOrEqual(string toCompare, string compareAgainst)
        {
            // convert to long in case there is any zero padding in the strings
            return IpAddressToLongBackwards(toCompare) >= IpAddressToLongBackwards(compareAgainst);
        }

        /// <summary>
        /// Compares two string representations of an Ip address to see if one
        /// is less than or equal to the other.
        /// </summary>
        /// <param name="toCompare">The IP address on the left hand side of the less 
        /// than or equal operator</param>
        /// <param name="compareAgainst">The Ip address on the right hand side of the 
        /// less than or equal operator</param>
        /// <returns>True if ToCompare is greater than or equal to CompareAgainst, else false</returns>
        private bool IsLessOrEqual(string toCompare, string compareAgainst)
        {
            // convert to long in case there is any zero padding in the strings
            return IpAddressToLongBackwards(toCompare) <= IpAddressToLongBackwards(compareAgainst);
        }

        /// <summary>
        /// Converts a uint representation of an Ip address to a string.
        /// </summary>
        /// <param name="ipAddress">The IP address to convert</param>
        /// <returns>A string representation of the IP address.</returns>
        private string LongToIpAddress(uint ipAddress)
        {
            return new System.Net.IPAddress(ipAddress).ToString();
        }

        /// <summary>
        /// Converts a string representation of an IP address to a uint. This
        /// encoding is proper and can be used with other networking functions such
        /// as the System.Net.IPAddress class.
        /// </summary>
        /// <param name="ipAddress">The Ip address to convert.</param>
        /// <returns>Returns a uint representation of the IP address.</returns>
        private uint IpAddressToLong(string ipAddress)
        {
            byte[] byteIp = System.Net.IPAddress.Parse(ipAddress).GetAddressBytes();

            uint ip = (uint)byteIp[3] << 24;
            ip += (uint)byteIp[2] << 16;
            ip += (uint)byteIp[1] << 8;
            ip += (uint)byteIp[0];

            return ip;
        }

        #endregion

        public BannedIpAddress GetBannedIpAddressById(int ipAddressId)
        {
            throw new NotImplementedException();
        }

        public List<BannedIpAddress> GetBannedIpAddressAll()
        {
            throw new NotImplementedException();
        }

        public void InsertBannedIpAddress(BannedIpAddress ipAddress)
        {
            throw new NotImplementedException();
        }

        public void UpdateBannedIpAddress(BannedIpAddress ipAddress)
        {
            throw new NotImplementedException();
        }

        public void DeleteBannedIpAddress(int ipAddressId)
        {
            throw new NotImplementedException();
        }

        public BannedIpNetwork GetBannedIpNetworkById(int bannedIpNetworkId)
        {
            throw new NotImplementedException();
        }

        public List<BannedIpNetwork> GetBannedIpNetworkAll()
        {
            throw new NotImplementedException();
        }

        public void InsertBannedIpNetwork(BannedIpNetwork ipNetwork)
        {
            throw new NotImplementedException();
        }

        public void UpdateBannedIpNetwork(BannedIpNetwork ipNetwork)
        {
            throw new NotImplementedException();
        }

        public void DeleteBannedIpNetwork(int bannedIpNetwork)
        {
            throw new NotImplementedException();
        }

        public bool IsIpAddressBanned(BannedIpAddress ipAddress)
        {
            throw new NotImplementedException();
        }

        public bool IsValidIp(string ipAddress)
        {
            throw new NotImplementedException();
        }
    }
}
